/*
	listfile (file_path, output_file) - Extract the contents of a file specified
	by <file_path> and store in output file.

	listfile is intended to behave like cat command. It should work only with 
	text file.
	
	output_file --> text file path (from local hard disk)

*/

#include <stdio.h>
#include <string.h>
#include "..//include//createvfs.h"
#include "..//include//n_ary.h"
#include "..//include//vfs_errorcodes.h"

int listfileop(char filepath[], char outputfile[], char filename_g[]) {
	
	struct Block b;
	struct header headervar;
	struct FD file_desc;

	FILE *fp, *f_out;

	char str[100], newstr1[100], newstr2[100], node_label[100], abspath[100];
	int num, j = 0, level = 0, count = 1, pos = 1, i, k = 0;
	int bnum;
	char fdpath[100], fname[50],c;
	char buffer[1024], ch;
	long int posn;
	
	// VFS_INSUFFICIENT_ARGUMENTS
	if ((strcmp(filepath,"") == 0) || (strcmp(outputfile,"") == 0)){
		printf("listfile_FAILURE %s\t",ERR_VFS_LISTFILE_00);
		return 0;
	}
	else {
		/*
			Traversing n-ary tree to search a file/ folder based on pathname
			and returning the corresponding node to the user.
		*/
	   Tree cur_tree;   
	   Tree prev_tree;
	   Tree sib = cur_tree;
	   Tree new;

	   NODE first = NULL;   
	   NODE cur = first;
	   NODE last;

	   // Split the path based on '/'
       while(filepath[pos]!='\0'){
			strcat(abspath,"/");	
	        j=0;
    	    num=splitlist(filepath,pos);
         
        	if(num>(strlen(filepath)-1)) 
        		num = strlen(filepath)-1;
         
	        for(i=pos; i<=num; i++){
    	        newstr2[j]=filepath[i];
    	        j++;
    	    }
        	newstr2[j]='\0';     
                strcat(abspath,newstr2);
	        first=insert_rear_ll(newstr2,abspath,first);
	        //strcat(abspath,newstr2);
         	if(num>=strlen(filepath)-1) 
         		break;
         	pos=num+2;
       }

      	last=cur;
      	cur=first;
      	while(cur->next!=NULL) {
        	count=count+1;
        	cur=cur->next;
      	}   
	
      	cur=first;
      	cur_tree=root->left;
      	sib=root->left;
      	prev_tree=root;     
      	while(count > 0){														// count = 1 => leaf node
			if(cur_tree!=NULL){ 
			   	if(strcmp(cur_tree->node_label,cur->entry) == 0 && count!=1){  // if (the two strings are equal) {...}
            		cur=cur->next;
           			prev_tree=cur_tree;
					cur_tree=cur_tree->left;
					sib=cur_tree;
					count=count-1;
       			}
       			else if(strcmp(cur_tree->node_label,cur->entry) == 0 && count==1){
       				count = count-1;
       			}
       			else {	// traverse to the right siblings
       				prev_tree = cur_tree;
       				cur_tree = cur_tree -> right;
       			}
       		}
       		else {
      			printf("listfile_FAILURE %s\n",ERR_VFS_LISTFILE_01);
				return 0;
       		}
      	}
     
	 	// cur_tree is the node to be listfiled.

		strcpy(fdpath,"");
	    strcat(fdpath,cur_tree->path);
	    strcat(fdpath,cur_tree->node_label);

		if (strstr(cur_tree -> node_label ,"txt") != NULL) {
			fp = fopen(filename_g, "rb+");
	 		if(fp==NULL) {
	 			printf("listfile_FAILURE %s\n",ERR_VFS_LISTFILE_01);
	 			return 0;
	 		}
	
			rewind(fp);
			fread(&headervar, sizeof(struct header), 1, fp);

			// seek to the start of FD block
			rewind(fp);
			fseek(fp, LABEL_SIZE*sizeof(char) + 2*(sizeof(int)), SEEK_SET); 
			
	 		i=0;
	 		while(i < headervar.total_desc) {
	 			fread(&file_desc, sizeof(struct FD), 1, fp);
	 			if (strcmp(file_desc.path,fdpath) == 0) {
						bnum = file_desc.blockno;
						// bnum will give the offset factor to the respective data block
						break;
				}
				i++;
	 		}
		 		
	 		rewind(fp);
	  		fseek(fp, sizeof(struct header)+sizeof(int)*num_blocks, SEEK_SET);
	  		// fseek to the starting position of the first block of the block list
	  		
			fseek(fp, 1024 * (bnum-1), SEEK_CUR);
			// fseek to the desired block number
						
			// open output file for writing
			 f_out = fopen(outputfile,"w+");
			 if (f_out == NULL) {
			 	  printf("listfile_FAILURE %s\n",ERR_VFS_LISTFILE_03);
	       		  return 0;
			 }


			// writing from the data block to the output file on hard disc		
			while((c = getc(fp))!= '\0') {
				//printf(" %c\t",c);
				putc(c,f_out);
			}
		}
		else {
			printf("listfile_FAILURE %s\n",ERR_VFS_LISTFILE_02);
	 		return 0;

		}
      
	}
	
	fclose(fp);
	fclose(f_out);
	return 1;	
}

int splitlist(char *str,int pos){
   int j,i;
   j=0;
   for(i=pos; i<strlen(str);i++){
      if(str[i]=='/' || str[i]=='"') return i-1;
   }
   
   return i;
}

